package view.mt4j.util;

import org.mt4j.components.MTComponent;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.widgets.MTTextArea;
import org.mt4j.components.visibleComponents.widgets.keyboard.ITextInputListener;
import org.mt4j.components.visibleComponents.widgets.keyboard.MTKeyboard;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
import org.mt4j.util.math.Vector3D;

import processing.core.PApplet;

public abstract class KeyboardHandler implements IGestureEventListener {
	public class Keyboard extends MTKeyboard {

		public Keyboard(PApplet pApplet) {
			super(pApplet);
		}

		@Override
		public void close() {
			super.close();
			onClose();
		}

		private void onClose() {
			KeyboardHandler.this.onClose();
		}

	}

	private MTKeyboard keyboard;
	private final MTTextArea textArea;
	private final PApplet pApplet;
	private final MTComponent parent;
	private final Vector3D parentRelativePosition;
	private boolean oneKeyboardPerParent = true;

	public KeyboardHandler(final PApplet pApplet, final MTKeyboard keyboard,
			final MTTextArea textArea, final MTComponent parent,
			final Vector3D parentRelativePosition) {
		super();
		this.pApplet = pApplet;
		this.keyboard = keyboard;
		this.textArea = textArea;
		this.parent = parent;
		this.parentRelativePosition = parentRelativePosition;
	}

	public void onClose() {

	}

	@Override
	public boolean processGestureEvent(MTGestureEvent ge) {
		TapEvent te = (TapEvent) ge;
		if (te.getId() == TapEvent.GESTURE_ENDED && te.isTapped()) {
			processKeyboardDisplay();
		}
		return false;
	}

	private void processKeyboardDisplay() {
		// remove all other keyboard if they are not the current
		if (oneKeyboardPerParent) {
			for (int i = 0; i < parent.getChildren().length; i++) {
				if (parent.getChildren()[i] instanceof MTKeyboard) {
					MTKeyboard otherKeyboard = (MTKeyboard) parent
							.getChildren()[i];
					if (keyboard == null || keyboard != null
							&& keyboard != otherKeyboard) {
						parent.removeChild(otherKeyboard);
						otherKeyboard.destroy();
					}
					// if (otherKeyboard.getBounds() != null
					// && keyboard != null
					// && keyboard == otherKeyboard
					// && otherKeyboard
					// .getCenterPointRelativeToParent()
					// .equalsVector(
					// parentRelativePosition.getAdded(new Vector3D(
					// 0,
					// keyboard.getHeightXY(TransformSpace.LOCAL) / 2)))) {
					// keyboard.removeFromParent();
					// parent.removeChild(keyboard);
					// keyboard.destroy();
					// }
				}
			}
		}
		if (keyboard == null || keyboard != null
				&& keyboard.getBounds() == null) {
			displayKeyboard(textArea);
		}
	}

	private void displayKeyboard(final ITextInputListener listener) {
		keyboard = new Keyboard(pApplet);

		parent.addChild(keyboard);
		keyboard.setPositionRelativeToParent(parentRelativePosition
				.getAdded(new Vector3D(0, keyboard
						.getHeightXY(TransformSpace.LOCAL) / 2)));
		keyboard.addTextInputListener(new TextAreaInputListener(listener) {

			@Override
			public void onTextChange() {
				KeyboardHandler.this.onTextChange();
			}

		});
	}

	public void updateTextFollowingTextArea() {
		// limit text to container
		if (textArea.getText().length() > 1) {
			textArea.setText(textArea.getText().substring(0,
					textArea.getText().length() - 1)
					+ " "
					+ textArea.getText()
							.charAt(textArea.getText().length() - 1));
			// not my fault, but the first line is not counted...
			if (textArea.getLineCount() > 0) {
				textArea.setText(textArea.getText().substring(0,
						textArea.getText().length() - 2));
			} else {
				textArea.setText(textArea.getText().replaceAll(" ", ""));
			}
		}
	}

	public abstract void onTextChange();

	public MTKeyboard getKeyboard() {
		return keyboard;
	}
}
